// src/message-handler.ts
// 消息处理器类，负责处理熊猫群聊和 Koishi (OneBot) 之间的消息转换和路由

import { Context, Session } from 'koishi';
import { TcpClient } from './tcp_client';
import { COMMAND_CODE, DELIMITER } from './constants';
import { encodePacket, decodePacket, getBotNickname, getGroupName } from './utils';

/**
 * 消息处理器类
 * 负责处理熊猫群聊和 Koishi (OneBot) 之间的消息转换和路由
 */
export class MessageHandler {
  private ctx: Context;
  private tcpClient: TcpClient;
  private botCache: Map<string, { nickname: string; online: boolean }> = new Map();

  constructor(ctx: Context, tcpClient: TcpClient) {
    this.ctx = ctx;
    this.tcpClient = tcpClient;
    this.setupEventHandlers();
  }

  /**
   * 获取机器人在线状态
   * 使用 Lagrange OneBot 的 get_status 接口
   */
  async getOnlineStatus(): Promise<boolean> {
    try {
      // 查找第一个 OneBot 机器人
      const bot = this.ctx.bots.find(b => b.platform === 'onebot');
      if (!bot) {
        return false;
      }

      // 调用 get_status 接口
      const response = await bot.internal._request('get_status', {});
      return response?.data?.online === true;
    } catch (error) {
      console.error('获取机器人在线状态失败:', error);
      return false;
    }
  }

  /**
   * 设置事件处理器
   */
  private setupEventHandlers(): void {
    // 监听TCP客户端的消息
    this.tcpClient.on('message', (data: string) => {
      this.handlePandaMessage(data);
    });

    // 监听TCP连接就绪事件
    this.tcpClient.on('ready', () => {
      console.log('熊猫群聊连接已建立，开始发送机器人信息');
      this.sendBotListToPanda();
    });

    // 监听Koishi的消息事件
    this.ctx.on('message', async (session) => {
      console.log(`[debug]${session.userId} 发送了消息: ${session.content}`);
      await this.handleKoishiMessage(session);
    });

    // 监听机器人上线事件
    this.ctx.on('bot-added', (bot) => {
      this.handleBotOnline(bot);
    });

    // 监听机器人下线事件
    this.ctx.on('bot-removed', (bot) => {
      this.handleBotOffline(bot);
    });

    // 监听好友请求事件
    this.ctx.on('friend-request', async (session) => {
      await this.handleFriendRequest(session);
    });

    // 监听群邀请事件
    this.ctx.on('guild-request', async (session) => {
      await this.handleGroupInvite(session);
    });
  }

  /**
   * 处理来自熊猫群聊的消息
   * @param data 接收到的原始数据
   */
  private handlePandaMessage(data: string): void {
    try {
      const parts = decodePacket(data);
      if (parts.length < 2) {
        console.warn('熊猫群聊消息格式错误:', data);
        return;
      }

      const commandCode = parts[0];
      console.log('收到熊猫群聊消息:', commandCode, parts);

      switch (commandCode) {
        case COMMAND_CODE.GROUP_MESSAGE:
          this.handlePandaGroupMessage(parts);
          break;
        case COMMAND_CODE.FRIEND_REQUEST:
          this.handlePandaFriendRequest(parts);
          break;
        case COMMAND_CODE.GROUP_INVITE:
          this.handlePandaGroupInvite(parts);
          break;
        case COMMAND_CODE.QUIT_GROUP:
          this.handlePandaQuitGroup(parts);
          break;
        case COMMAND_CODE.QUIT_NON_WORK_GROUPS:
          this.handlePandaQuitNonWorkGroups(parts);
          break;
        case COMMAND_CODE.ADD_FRIEND:
          this.handlePandaAddFriend(parts);
          break;
        case COMMAND_CODE.JOIN_GROUP:
          this.handlePandaJoinGroup(parts);
          break;
        case COMMAND_CODE.REFRESH_NICKNAME:
          this.handlePandaRefreshNickname(parts);
          break;
        default:
          console.log('未知的熊猫群聊命令码:', commandCode);
      }
    } catch (error) {
      console.error('处理熊猫群聊消息时出错:', error);
    }
  }

  /**
   * 处理熊猫群聊的群消息发送请求
   * 格式: 2→←机器人QQ→←群号→←消息内容→←气泡ID→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaGroupMessage(parts: string[]): Promise<void> {
    if (parts.length < 5) {
      console.warn('群消息格式错误:', parts);
      return;
    }

    const [, botQQ, groupId, , messageContent, bubbleId] = parts;
    
    try {
      // 查找对应的机器人会话
      const bot = this.ctx.bots.find(b => b.selfId === botQQ && b.platform === 'onebot');
      if (!bot) {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 发送群消息
      await bot.internal._request('send_group_msg', {
        group_id: parseInt(groupId),
        message: messageContent
      });
      console.log(`已发送群消息到 ${groupId}: ${messageContent}`);
    } catch (error) {
      console.error('发送群消息失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的好友请求处理
   * 格式: 102→←机器人QQ→←申请人QQ→←验证消息→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaFriendRequest(parts: string[]): Promise<void> {
    if (parts.length < 4) {
      console.warn('好友请求格式错误:', parts);
      return;
    }

    const [, botQQ, userQQ, message] = parts;
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ && b.platform === 'onebot');
      if (!bot) {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 同意好友请求
      await bot.internal._request('set_friend_add_request', {
        flag: userQQ, // 使用用户QQ作为flag
        approve: true,
        remark: ''
      });

      console.log(`已同意好友请求: ${userQQ}`);
    } catch (error) {
      console.error('处理好友请求失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的群邀请处理
   * 格式: 103→←机器人QQ→←群号→←邀请人QQ→←消息ID→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaGroupInvite(parts: string[]): Promise<void> {
    if (parts.length < 5) {
      console.warn('群邀请格式错误:', parts);
      return;
    }

    const [, botQQ, groupId, inviterQQ, messageId] = parts;
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ && b.platform === 'onebot');
      if (!bot) {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 同意群邀请
      await bot.internal._request('set_group_add_request', {
        flag: messageId,
        sub_type: 'invite',
        approve: true
      });

      console.log(`已同意群邀请: ${groupId}`);
    } catch (error) {
      console.error('处理群邀请失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的退群请求
   * 格式: 9→←机器人QQ→←群号→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaQuitGroup(parts: string[]): Promise<void> {
    if (parts.length < 3) {
      console.warn('退群请求格式错误:', parts);
      return;
    }

    const [, botQQ, groupId] = parts;
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ && b.platform === 'onebot');
      if (!bot) {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 退出群聊
      await bot.internal._request('set_group_leave', {
        group_id: parseInt(groupId),
        is_dismiss: false
      });

      console.log(`已退出群聊: ${groupId}`);
    } catch (error) {
      console.error('退出群聊失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的批量退群请求
   * 格式: 99→←机器人QQ→←保留群号列表(用|分隔)→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaQuitNonWorkGroups(parts: string[]): Promise<void> {
    if (parts.length < 3) {
      console.warn('批量退群请求格式错误:', parts);
      return;
    }

    const [, botQQ, keepGroupsStr] = parts;
    const keepGroups = keepGroupsStr.split('|').filter(g => g.trim());
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ && b.platform === 'onebot');
      if (!bot) {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 获取群列表
      const groupList = await bot.internal._request('get_group_list', {});
      
      // 退出不在保留列表中的群
      for (const group of groupList.data || []) {
        const groupId = group.group_id.toString();
        if (!keepGroups.includes(groupId)) {
          try {
            await bot.internal._request('set_group_leave', {
              group_id: group.group_id,
              is_dismiss: false
            });
            console.log(`已退出非工作群: ${groupId}`);
          } catch (error) {
            console.error(`退出群 ${groupId} 失败:`, error);
          }
        }
      }
    } catch (error) {
      console.error('批量退群失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的添加好友请求
   * 格式: 105→←机器人QQ→←目标QQ→←验证消息→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaAddFriend(parts: string[]): Promise<void> {
    if (parts.length < 4) {
      console.warn('添加好友请求格式错误:', parts);
      return;
    }

    const [, botQQ, targetQQ, message] = parts;
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ);
      if (!bot || bot.platform !== 'onebot') {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 添加好友 (OneBot标准中没有直接的添加好友API，这里可能需要根据具体实现调整)
      console.log(`尝试添加好友: ${targetQQ}, 验证消息: ${message}`);
      // 注意：OneBot标准中没有主动添加好友的API，这里可能需要其他方式实现
    } catch (error) {
      console.error('添加好友失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的加群请求
   * 格式: 106→←机器人QQ→←群号→←验证消息→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaJoinGroup(parts: string[]): Promise<void> {
    if (parts.length < 4) {
      console.warn('加群请求格式错误:', parts);
      return;
    }

    const [, botQQ, groupId, message] = parts;
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ);
      if (!bot || bot.platform !== 'onebot') {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 加入群聊 (OneBot标准中没有直接的加群API，这里可能需要根据具体实现调整)
      console.log(`尝试加入群聊: ${groupId}, 验证消息: ${message}`);
      // 注意：OneBot标准中没有主动加群的API，这里可能需要其他方式实现
    } catch (error) {
      console.error('加入群聊失败:', error);
    }
  }

  /**
   * 处理熊猫群聊的刷新昵称请求
   * 格式: 201→←机器人QQ→←
   * @param parts 分割后的消息部分
   */
  private async handlePandaRefreshNickname(parts: string[]): Promise<void> {
    if (parts.length < 2) {
      console.warn('刷新昵称请求格式错误:', parts);
      return;
    }

    const [, botQQ] = parts;
    
    try {
      const bot = this.ctx.bots.find(b => b.selfId === botQQ && b.platform === 'onebot');
      if (!bot) {
        console.warn(`未找到OneBot机器人: ${botQQ}`);
        return;
      }

      // 获取机器人信息
      const loginInfo = await bot.internal._request('get_login_info', {});
      const nickname = loginInfo?.data?.nickname || '';

      // 发送昵称信息回熊猫群聊
      const response = encodePacket('201', botQQ, nickname);
      this.tcpClient.send(response);

      console.log(`已刷新机器人昵称: ${botQQ} -> ${nickname}`);
    } catch (error) {
      console.error('刷新昵称失败:', error);
    }
  }

  /**
   * 处理来自Koishi的消息
   * @param session 消息会话
   */
  private async handleKoishiMessage(session: Session): Promise<void> {
    // 只处理群消息
    if (!session.guildId) {
      return;
    }

    try {
      // 获取群名称和机器人昵称
      const groupName = await this.getGroupName(session);
      console.log(`[debug]群名称: ${groupName}`);
      const botNickname = await this.getBotNickname(session);

      // 发送群消息到熊猫群聊
      // 格式: 2→←机器人→←消息来源→←发信人→←消息内容→←机器人昵称→←群昵称→←
      // 注意：这里的参数顺序要与易语言代码完全一致
      const packet = encodePacket(
        COMMAND_CODE.GROUP_MESSAGE,
        session.selfId,
        session.guildId,
        session.userId,
        session.content || '',
        botNickname,
        groupName
      );

      console.log(`[debug]发送数据包: ${packet}`);
      this.tcpClient.send(packet);
      console.log(`已转发群消息到熊猫群聊: ${session.guildId}`);
    } catch (error) {
      console.error('转发消息到熊猫群聊失败:', error);
    }
  }

  /**
   * 处理机器人上线事件
   * @param bot 机器人实例
   */
  private handleBotOnline(bot: any): void {
    this.botCache.set(bot.selfId, {
      nickname: bot.user?.name || '',
      online: true
    });

    // 发送登录事件到熊猫群聊
    this.sendBotLoginToPanda(bot.selfId, bot.user?.name || '');
  }

  /**
   * 处理机器人下线事件
   * @param bot 机器人实例
   */
  private handleBotOffline(bot: any): void {
    const cached = this.botCache.get(bot.selfId);
    if (cached) {
      cached.online = false;
    }

    // 发送离线事件到熊猫群聊
    this.sendBotOfflineToPanda(bot.selfId);
  }

  /**
   * 处理好友请求事件
   * @param session 会话
   */
  private async handleFriendRequest(session: Session): Promise<void> {
    try {
      // 发送好友请求到熊猫群聊
      // 格式: 102→←机器人QQ→←申请人QQ→←验证消息→←
      const packet = encodePacket(
        COMMAND_CODE.FRIEND_REQUEST,
        session.selfId,
        session.userId,
        session.content || ''
      );

      this.tcpClient.send(packet);
      console.log(`已转发好友请求到熊猫群聊: ${session.userId}`);
    } catch (error) {
      console.error('转发好友请求失败:', error);
    }
  }

  /**
   * 处理群邀请事件
   * @param session 会话
   */
  private async handleGroupInvite(session: Session): Promise<void> {
    try {
      // 发送群邀请到熊猫群聊
      // 格式: 103→←机器人QQ→←群号→←邀请人QQ→←消息ID→←
      const packet = encodePacket(
        COMMAND_CODE.GROUP_INVITE,
        session.selfId,
        session.guildId || '',
        session.userId,
        session.messageId || ''
      );

      this.tcpClient.send(packet);
      console.log(`已转发群邀请到熊猫群聊: ${session.guildId}`);
    } catch (error) {
      console.error('转发群邀请失败:', error);
    }
  }

  /**
   * 发送机器人列表到熊猫群聊
   */
  private sendBotListToPanda(): void {
    for (const bot of this.ctx.bots) {
      if (bot.status === 'online' as any) {
        this.sendBotLoginToPanda(bot.selfId, bot.user?.name || '');
      }
    }
  }

  /**
   * 发送机器人登录事件到熊猫群聊
   * @param botQQ 机器人QQ号
   * @param nickname 机器人昵称
   */
  private sendBotLoginToPanda(botQQ: string, nickname: string): void {
    // 格式: 100→←机器人|QQ→←昵称→←
    // 注意：易语言代码中机器人QQ后面要加上"|QQ"
    const packet = encodePacket(COMMAND_CODE.ONLINE, `${botQQ}|QQ`, nickname);
    this.tcpClient.send(packet);
    console.log(`已发送机器人登录信息到熊猫群聊: ${botQQ}`);
  }

  /**
   * 发送机器人离线事件到熊猫群聊
   * @param botQQ 机器人QQ号
   */
  private sendBotOfflineToPanda(botQQ: string): void {
    // 格式: 101→←机器人QQ→←
    const packet = encodePacket(COMMAND_CODE.OFFLINE, botQQ);
    this.tcpClient.send(packet);
    console.log(`已发送机器人离线信息到熊猫群聊: ${botQQ}`);
  }

  /**
   * 获取群名称
   * @param session 会话
   * @returns 群名称
   */
  private async getGroupName(session: Session): Promise<string> {
    try {
      if (!session.guildId || session.bot.platform !== 'onebot') {
        return '';
      }

      const groupInfo = await session.bot.internal._request(
        'get_group_info',
        {
          group_id: session.guildId
        }
      );
      // console.log(`获取群信息: ${JSON.stringify(groupInfo)}`);

      return groupInfo.data.group_name || '';
    } catch (error) {
      console.error('获取群名称失败:', error);
      return '';
    }
  }

  /**
   * 获取机器人昵称
   * @param session 会话
   * @returns 机器人昵称
   */
  private async getBotNickname(session: Session): Promise<string> {
    try {
      const cached = this.botCache.get(session.selfId);
      if (cached?.nickname) {
        return cached.nickname;
      }

      if (session.bot.platform !== 'onebot') {
        return session.bot.user?.name || '';
      }

      const loginInfo = await session.bot.internal._request('get_login_info', {});
      // console.log(`获取登录信息: ${JSON.stringify(loginInfo)}`);

      const nickname = loginInfo?.data?.nickname || '';

      // 更新缓存
      this.botCache.set(session.selfId, {
        nickname,
        online: true
      });

      return nickname;
    } catch (error) {
      console.error('获取机器人昵称失败:', error);
      return session.bot.user?.name || '';
    }
  }
}